package GoodsService

import (
	"context"
	"gdshop-admin-go-api/app/request/GoodsReq"
	"gdshop-admin-go-api/library/response"
	toolsDb "gdshop-admin-go-api/library/tools/db"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gvalid"
	"strings"
	"time"
)

func GetQuickEditForm(ctx context.Context, typeStr, goodsId string) *response.JsonResponse {
	if len(typeStr) < 1 {
		return response.FailByRequestMessage(nil, "类型不能为空")
	}
	if len(goodsId) < 1 {
		return response.FailByRequestMessage(nil, "商品ID 不能为空")
	}
	allowType := g.Map{
		"price": "id,title,market_price,sell_price,cost_price",
		"stock": "id,title,stock,stock AS new_stock",
	}
	res, err := toolsDb.GetUnSafaTableAddDeleteWhere(ctx, "goods_option").Where("goods_id",
		goodsId).Order("display_sort DESC").Fields(allowType[typeStr]).All()
	if err != nil {
		return response.FailByRequestMessage(nil, err.Error())
	}
	return response.SuccessByRequestMessageData(nil, "成功", res.List())
}

func getQuickEditFormOptionData(typeStr string, setData g.Map) g.Map {
	delete(setData, "id")
	if typeStr == "stock" {
		return g.Map{
			"stock": setData["new_stock"],
		}
	}
	if typeStr == "price" {
		return g.Map{
			"market_price": setData["new_market_price"],
			"sell_price":   setData["new_sell_price"],
			"cost_price":   setData["new_cost_price"],
		}
	}
	return g.Map{}
}

func GoodsChangeRelated(tx *gdb.TX, typeStr string, goodsId int) error {
	dbPrefix := g.Cfg().GetString("database.prefix")
	if typeStr == "stock" {
		sql := "UPDATE " + dbPrefix + "goods g SET `stock` = "
		sql += "(SELECT IFNULL(SUM(go.stock),0) FROM " + dbPrefix + "goods_option go WHERE"
		sql += " go.delete_at < 1 AND go.is_open = 1 AND go.goods_id = g.id ) WHERE `id` = ?"
		// 更新总库存
		_, err := tx.Exec(sql,
			goodsId)
		if err != nil {
			return err
		}
	}
	if typeStr == "price" {
		// 更新最小价格和最大价格
		sql := "UPDATE " + dbPrefix + "goods g SET "
		sql += "`min_price` = (SELECT IFNULL(MIN(go.sell_price),0) FROM " + dbPrefix + "goods_option go WHERE go.delete_at < 1 AND go.is_open = 1 AND go.goods_id = g.id )"
		sql += ","
		sql += "`max_price` = (SELECT IFNULL(MAX(go.sell_price),0) FROM " + dbPrefix + "goods_option go WHERE go.delete_at < 1 AND go.is_open = 1 AND go.goods_id = g.id )"
		sql += " WHERE `id` = ?"

		_, err := tx.Exec(sql,
			goodsId)
		if err != nil {
			return err
		}
	}

	return nil
}

func SetQuickEditForm(ctx context.Context, typeStr string, goodsId int, setData []map[string]interface{}) *response.JsonResponse {
	if len(typeStr) < 1 {
		return response.FailByRequestMessage(nil, "类型不能为空")
	}
	if goodsId < 1 {
		return response.FailByRequestMessage(nil, "商品ID 不能为空")
	}
	//fmt.Println("setData " , setData)
	//return response.FailByRequestMessage(nil,"失败")
	tx, err := g.DB().Ctx(ctx).Begin()
	if err != nil {
		return response.FailByRequestMessage(nil, err.Error())
	}
	for _, item := range setData {
		_, err := tx.Model("goods_option").Unscoped().Where(
			"goods_id = ? AND id = ?", goodsId, item["id"]).Update(
			getQuickEditFormOptionData(typeStr, item))
		if err != nil {
			return response.FailByRequestMessage(nil, err.Error())
		}
	}
	// 更新总库存 ，更新最小价格和最大价格
	err = GoodsChangeRelated(tx, typeStr, goodsId)
	if err != nil {
		return response.FailByRequestMessage(nil, err.Error())
	}

	err = tx.Commit()
	if err != nil {
		return response.FailByRequestMessage(nil, err.Error())
	}
	return response.SuccessByRequestMessage(nil, "成功")
}

func getCheckAttrs(checkAttrs []string, keyName string) int {
	for _, item := range checkAttrs {
		if item == keyName {
			return 1
		}
	}

	return 0
}

func saveGoodsExtendByTx(tx *gdb.TX, data g.Map) error {
	_, err := tx.Model("goods_extend").Unscoped().Save(data)
	if err != nil {
		return err
	}

	return nil
}

func saveGoodsOptionByTx(tx *gdb.TX, goodsId int, datas []*GoodsReq.SpecTableItem) error {
	// 先删除原来的数据
	_, err := tx.Model("goods_option").Unscoped().Where("goods_id",
		goodsId).Update(g.Map{
		"delete_at": time.Now().Unix(),
	})
	if err != nil {
		return err
	}
	for _, item := range datas {
		item.SpecsText = strings.Join(item.Specs, "_")
		item.CreateAt = time.Now().Unix()
		if item.IsOpen {
			item.IsOpenInt = 1
		}
		_, err := tx.Model("goods_option").Unscoped().Insert(item)
		if err != nil {
			return err
		}
	}

	return nil
}

// 检测是新增还是编辑 false 为编辑
func specsCheckAddOrEdit(idStr string) bool {
	if err := gvalid.CheckValue(context.Background(), idStr, "integer", nil); err != nil {
		// 有错误，说明不是整数，就是新增
		return true
	} else {
		return false
	}
}

func saveGoodsSpecsByTx(tx *gdb.TX, goodsId int, specsData []*GoodsReq.Specs, optionData []*GoodsReq.SpecTableItem) error {
	// goods_spec
	var keys []string
	specItemIds := g.MapStrStr{}
	specsLen := len(specsData) + 1

	// 取出原 optionSpecss
	specsArr, err := tx.Model("goods_option").Unscoped().Where(
		"delete_at < 1 and goods_id = ?", goodsId).Array("specs")
	if err != nil {
		return err
	}
	optionSpecss := []string{}
	for _, item := range specsArr {
		optionSpecss = append(optionSpecss, item.String())
	}

	// 把原来 goods_spec 的先设置为删除状态
	_, err = tx.Model("goods_spec").Unscoped().Where("goods_id", goodsId).Update(g.Map{
		"delete_at": time.Now().Unix(),
	})
	if err != nil {
		return err
	}

	// 保存规格
	for key, item := range specsData {
		tmpData := g.Map{
			"goods_id":     goodsId,
			"title":        item.Value,
			"display_sort": specsLen - key,
		}
		specId := ""
		if !specsCheckAddOrEdit(item.Id) {
			tmpData["id"] = item.Id
			specId = item.Id
			tmpData["update_at"] = time.Now().Unix()
			tmpData["delete_at"] = 0
			_, err := tx.Model("goods_spec").Unscoped().Where("id", item.Id).Update(tmpData)
			if err != nil {
				return err
			}
		} else {
			tmpData["create_at"] = time.Now().Unix()
			id, err := tx.Model("goods_spec").Unscoped().InsertAndGetId(tmpData)
			if err != nil {
				return err
			}
			specId = gconv.String(id)
		}
		// goods_spec_item
		itemLen := len(item.Items) + 1
		for zk, zi := range item.Items {
			ziData := g.Map{
				"goods_id":     goodsId,
				"spec_id":      specId,
				"title":        zi.Value,
				"thumb":        zi.Thumb,
				"display_sort": itemLen - zk,
			}
			siId := ""
			if !specsCheckAddOrEdit(zi.Id) {
				ziData["id"] = zi.Id
				siId = zi.Id
				ziData["update_at"] = time.Now().Unix()
				_, err := tx.Model("goods_spec_item").Unscoped().Where("id", zi.Id).Update(ziData)
				if err != nil {
					return err
				}
			} else {
				ziData["create_at"] = time.Now().Unix()
				id, err := tx.Model("goods_spec_item").Unscoped().InsertAndGetId(ziData)
				if err != nil {
					return err
				}
				siId = gconv.String(id)
			}
			specItemIds[zi.Id] = siId
			keys = append(keys, zi.Id)
		}
	}
	/*fmt.Println(specItemIds)
	fmt.Println(keys)*/
	// goods_option
	goLen := len(optionData) + 1
	// 只统计 开启的库存
	totalStock := 0
	tmpSpecs := ""
	// 新的 specs
	newSpecs := []string{}
	for goKey, item := range optionData {
		tmp := []string{}
		for _, keyName := range keys {
			for _, s := range item.Specs {
				if s == keyName {
					tmp = append(tmp, specItemIds[keyName])
				}
			}
		}
		tmpSpecs = strings.Join(tmp, "_")

		if item.IsOpen {
			totalStock += item.Stock
		}

		// 保存数据
		tmpData := g.Map{
			"goods_id":     goodsId,
			"title":        item.Title,
			"thumb":        item.Thumb,
			"market_price": item.MarketPrice * 100,
			"sell_price":   item.SellPrice * 100,
			"cost_price":   item.CostPrice * 100,
			"stock":        item.Stock,
			"display_sort": goLen - goKey,
			"goods_sn":     item.GoodsSku,
			"specs":        tmpSpecs,
		}
		//fmt.Println(tmp)
		//fmt.Println(tmpData["specs"])
		if item.IsOpen {
			tmpData["is_open"] = 1
		} else {
			tmpData["is_open"] = 0
		}
		if gstr.InArray(optionSpecss, tmpSpecs) {
			_, err := tx.Model("goods_option").Unscoped().Where("specs",
				tmpSpecs).Update(tmpData)
			if err != nil {
				return err
			}
		} else {
			_, err := tx.Model("goods_option").Unscoped().Insert(tmpData)
			if err != nil {
				return err
			}
		}
		newSpecs = append(newSpecs, tmpSpecs)
	}
	optionSpecss = append(optionSpecss, newSpecs...)
	// 对比 specs ，删除多余数据
	delSpecs := []string{}
	for _, item := range optionSpecss {
		// 只要不在 newSpecs 里面的都需要删除
		if !gstr.InArray(newSpecs, item) {
			delSpecs = append(delSpecs, item)
		}
	}
	if len(delSpecs) > 0 {
		// 删除老的 goods_option 数据
		_, err = tx.Model("goods_option").Where("specs IN (?)", delSpecs).Update(g.Map{
			"delete_at": time.Now().Unix(),
		})
		if err != nil {
			return err
		}
	}

	// 更新总库存
	err = GoodsChangeRelated(tx, "stock", goodsId)
	if err != nil {
		return err
	}
	// 更新最小价格和最大价格
	err = GoodsChangeRelated(tx, "price", goodsId)
	if err != nil {
		return err
	}

	return nil
}
